package single;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

/**
 * @projectName: JUC
 * @package: single
 * @className: LazyMan
 * @author: 冷环渊 doomwatcher
 * @description: TODO
 * @date: 2022/3/4 17:09
 * @version: 1.0
 */
public class LazyMan {
    private static boolean flag = true;

    private LazyMan() {
        synchronized (LazyMan.class) {
            if (flag == false) {
                flag = true;
            } else {
                throw new RuntimeException("不要试图用反射破坏单例模式");
            }
            if (lazyMan != null) {
                throw new RuntimeException("不要试图用反射破坏单例模式");
            }
        }
    }

    //必须 加上 volatile 避免 指令重排
    private volatile static LazyMan lazyMan;

    // 双重检测锁模式 的懒汉式单例 DCL懒汉式
    public static LazyMan getInstance() {
        if (lazyMan == null) {
            synchronized (LazyMan.class) {
                if (lazyMan == null) {
                    lazyMan = new LazyMan();
                    //    会有问题 不是一个原子性操作
                    /* 1. 分配内存空间
                     * 2 。 执行构造对象 初始化对象
                     * 3. 把这个对象指向空间
                     *
                     * 比如 我们期望执行的是 123
                     * 但是 指令重排 执行是 132
                     * a 线程可能没有问题，
                     * b 就会以为已经完成构造，指向就是null 可能会空指针
                     * */
                }
            }
        }
        return lazyMan;
    }

    //但是会有并发问题
    public static void main(String[] args) throws NoSuchFieldException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        Constructor<EnumSngle> field = EnumSngle.class.getDeclaredConstructor(String.class, int.class);
        field.setAccessible(true);
        //LazyMan lazyMan = field.newInstance();
        //LazyMan lazyMan1 = field.newInstance();
        EnumSngle lazyMan = field.newInstance();
        EnumSngle lazyMan1 = field.newInstance();

        System.out.println(lazyMan);
        System.out.println(lazyMan1);
    }
}
